﻿using System;
using System.Collections.Specialized;
using ActivateYourGlutes.Model.Providers;
using Microsoft.Practices.ServiceLocation;

namespace ActivateYourGlutes.Model.Internal
{
    public partial class MeasurementType
    {
        public const string Absolute = "A";
        public const string Percentage = "P";
        public const string Length = "L";
        public const string Weight = "W";

        public bool IsAbsolute { get { return Type == Absolute; } }

        public bool IsPercentage { get { return Type == Percentage; } }

        public bool IsWeight { get { return Type == Weight; } }

        public bool IsLength { get { return Type == Length; } }

        public string Unit
        {
            get
            {
                string unit = "";
                if (IsPercentage)
                    unit = "%";
                else if (IsWeight)
                {
                    var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                    unit = localisationProvider.UnitOfWeight.Unit;
                }
                else if (IsLength)
                {
                    var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                    unit = localisationProvider.UnitOfLength.Unit;
                }
                return unit;
            }
        }

        public double LocaliseValue(double value)
        {
            if (IsAbsolute || IsPercentage)
                return value;
            if (IsWeight)
            {
                var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                var weightMultiplier = localisationProvider.UnitOfWeight.ToKgMultiplier;
                return Math.Round(value / weightMultiplier, 1);
            }
            if (IsLength)
            {
                var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                var lengthMultiplier = localisationProvider.UnitOfLength.ToMetersMultiplier;
                return Math.Round(value / lengthMultiplier, 1);
            }
            throw new ModelException("A unit of measurement is in use that does not have associated localisation logic.");
        }

        public double DelocaliseValue(double value)
        {
            if (IsAbsolute || IsPercentage)
                return value;
            if (IsWeight)
            {
                var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                var weightMultiplier = localisationProvider.UnitOfWeight.ToKgMultiplier;
                return value * weightMultiplier;
            }
            if (IsLength)
            {
                var localisationProvider = ServiceLocator.Current.GetInstance<ILocalisationProvider>();
                var lengthMultiplier = localisationProvider.UnitOfLength.ToMetersMultiplier;
                return value * lengthMultiplier;
            }
            throw new ModelException("A unit of measurement is in use that does not have associated localisation logic.");
        }

        public void ValidateValue(double value, NameValueCollection errors)
        {
            if (IsPercentage)
            {
                if (value < 1 || value > 100)
                    errors.Add(String.Format("MT_{0}", MeasurementTypeId),
                        String.Format("{0} must be in the range 1 to 100", Description));
            }
            else if (IsLength || IsWeight || IsAbsolute)
            {
                if (value <= 0)
                    errors.Add(String.Format("MT_{0}", MeasurementTypeId),
                        String.Format("{0} must be greater than zero", Description));
            }
        }

        public NameValueCollection Validate()
        {
            var errors = new NameValueCollection();
            if (String.IsNullOrEmpty(Type))
                errors.Add("Type", "Measurement value type must be specified");
            if (String.IsNullOrEmpty(Description))
                errors.Add("Description", "Description is required");
            else if (Description.Length > 256)
                errors.Add("Description", "Description has exceeded the maximum length");
            return errors;
        }
    }
}
